package com.decheng.mongo.controller;

import com.decheng.mongo.entity.User;
import com.decheng.mongo.result.ApiResult;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.regex.Pattern;

/**
 * @author 孔德成
 * @slogan 致敬大师，致敬未来的你
 * @date 2021/9/1 2:41 下午
 * @desc 使用 MongoTemplate 开发 CRUD
 */
@Api(tags = "MongoTemplate Api 测试")
@RestController
@RequestMapping("/mongo/t")
@Slf4j
public class MongoTemplateController {

    private final MongoTemplate mongoTemplate;

    public MongoTemplateController(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }


    @ApiOperation("保存用户")
    @PostMapping("saveUser")
    public ApiResult saveUser(@RequestBody User user) {
        return ApiResult.ok().data("item", mongoTemplate.save(user));
    }

    @ApiOperation("查询所有用户")
    @GetMapping("findAll")
    public ApiResult findAllUser() {
        return ApiResult.ok().data(mongoTemplate.findAll(User.class));
    }

    @ApiOperation("根据id查询")
    @GetMapping("findById/{id}")
    public ApiResult getUserById(@PathVariable String id) {
        return ApiResult.ok().data("item", mongoTemplate.findById(id, User.class));
    }

    @ApiOperation("根据姓名和年龄查询用户")
    @GetMapping("findUser")
    public ApiResult findUserList(@RequestParam String name, @RequestParam(required = false) Integer age) {
        // 1. 创建查询条件
        Criteria criteria = Criteria.where("name").is(name);
        // where name=name and age=age
        if (age != null) {
            criteria.and("age").is(age);
        }
        Query query = new Query(criteria);
        return ApiResult.ok().data(mongoTemplate.find(query, User.class));
    }

    @ApiOperation("模糊查询")
    @GetMapping("findLike")
    public ApiResult findUsersLikeName(@RequestParam String name) {
        // 1. 创建正则表达式
        // 等价于 like %name%
        String regex = String.format("%s%s%s", "^.*", name, ".*$");
        // Pattern.CASE_INSENSITIVE 不区分大小写
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        // 2. 创建查询条件
        Query query = new Query(Criteria.where("name").regex(pattern));
        return ApiResult.ok().data(mongoTemplate.find(query, User.class));
    }

    @ApiOperation("分页查询")
    @GetMapping("findPage/{current}/{size}")
    public ApiResult findUsersPage(@PathVariable long current, @PathVariable int size) {
        // 1. 创建查询条件
        Query query = new Query();
        // 2. 查询记录总数
        long total = mongoTemplate.count(query, User.class);
        // 3. 获取分页数据
        // skip 跳过前 n 条数据
        // limit 获取 n 条件数据
        List<User> userList = mongoTemplate.find(query.skip((current - 1) * size).limit(size), User.class);

        return ApiResult.ok().data(total, userList);
    }

    @ApiOperation("修改")
    @PutMapping("update")
    public ApiResult updateUser(@RequestBody User user) {
        // 1. where _id = id
        Query query = new Query(Criteria.where("_id").is(user.getId()));
        // 2. 设置修改内容
        Update update = new Update();
        update.set("name", user.getName());
        update.set("age", user.getAge());
        update.set("email", user.getEmail());
        // 3. 执行更新操作
        UpdateResult result = mongoTemplate.upsert(query, update, User.class);
        // 等价于受影响行数
        log.info("更新行数: " + result.getModifiedCount());
        return ApiResult.ok().data("result", result);
    }

    @ApiOperation("删除操作")
    @DeleteMapping("delete/{id}")
    public ApiResult deleteById(@PathVariable String id) {
        Query query = new Query(Criteria.where("_id").is(id));
        DeleteResult result = mongoTemplate.remove(query, User.class);
        // 等价于受影响行数
        log.info("删除行数: " + result.getDeletedCount());
        return ApiResult.ok().data("result", result);
    }
}
